import json

from django import http
from django.core.paginator import Paginator, EmptyPage
from django.shortcuts import render
from django.views import View
from django_redis import get_redis_connection

from apps.goods.models import GoodsCategory, SKU
from apps.goods.utils import get_categories, get_breadcrumb
from utils import constants
from utils.response_code import RETCODE
from utils.views import LoginRequiredJSONMixin


class ListView(View):
    """商品列表页"""

    def get(self, request, category_id, page_num):
        """提供商品列表页"""
        # 判断category_id是否正确
        try:
            category = GoodsCategory.objects.get(id=category_id)
        except GoodsCategory.DoesNotExist:
            return http.HttpResponseNotFound('GoodsCategory does not exist')

        # 查询商品频道和分类
        categories = get_categories()
        # 查询面包屑导航
        breadcrumb = get_breadcrumb(category)

        # 接收sort参数：如果用户不传 就是默认的排序规则
        sort = request.GET.get('sort', 'default')

        # 按照排序规则查询该分类商品SKU信息
        if sort == 'price':
            # 按照价格由低到高
            sort_field = 'price'
        elif sort == 'hot':
            # 按照销量由低到高
            sort_field = '-sales'
        else:
            # 'price'和'sales'以外的所有排列方式都归为'default'
            sort = 'default'
            sort_field = 'create_time'

        skus = SKU.objects.filter(spu__category3=category, is_launched=True).order_by(sort_field)

        # 创建分页器：每页N条记录
        paginator = Paginator(skus, constants.GOODS_LIST_LIMIT)
        # 获取每页商品数据
        try:
            page_skus = paginator.page(page_num)
        except EmptyPage:
            # 如果page_num不正确 默认给用户404
            return http.HttpResponseNotFound('empty page')
        # 获取列表页总页数
        total_page = paginator.num_pages

        # 定义一个字典 用来传递到渲染的过程中使用
        context = {
            'categories': categories,
            'breadcrumb': breadcrumb,
            'category': category,
            'sort': sort,  # 排序字段
            'page_skus': page_skus,  # 分页后数据
            'total_page': total_page,  # 总页数
            'page_num': page_num,  # 当前页码
        }

        return render(request, 'list.html', context)


class HotGoodsView(View):
    """商品热销排行"""

    def get(self, request, category_id):
        """提供商品热销排行JSON数据"""
        # 根据销量倒序
        skus = SKU.objects.filter(category_id=category_id, is_launched=True).order_by('-sales')[:2]

        # 序列化
        hot_skus = []
        for sku in skus:
            hot_skus.append({
                'id': sku.id,
                'default_image_url': sku.default_image,
                'name': sku.name,
                'price': sku.price
            })

        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'hot_skus': hot_skus})


class DetailView(View):
    """商品详情页"""

    def get(self, request, sku_id):
        """提供商品详情页"""
        # 获取当前sku的信息
        try:
            sku = SKU.objects.get(id=sku_id)
        except SKU.DoesNotExist:
            return render(request, '404.html')

        # 查询商品频道分类
        categories = get_categories()

        # 查询面包屑导航
        category = sku.spu.category3
        breadcrumb = get_breadcrumb(category)

        # 取出所有的spu下的sku
        spu_specs_dict = {}
        all_skus = sku.spu.sku_set.all()
        for sku_temp in all_skus:
            one_sku_specs = sku_temp.specs.all()
            for one_sku_spec in one_sku_specs:
                if (one_sku_spec.spec.name, one_sku_spec.option.value) not in spu_specs_dict:
                    spu_specs_dict[(one_sku_spec.spec.name, one_sku_spec.option.value)] = {sku_temp.id}
                else:
                    spu_specs_dict[(one_sku_spec.spec.name, one_sku_spec.option.value)].add(sku_temp.id)

        for op, val in spu_specs_dict.items():
            if sku.id in val:
                set_temp = val - {sku.id}  # 例如 {8，6}
                spu_specs_dict[op] = {sku.id}  # 例如{4}
                for op_2, val_2 in spu_specs_dict.items():
                    for sku_id in set_temp:
                        if sku_id in val_2:
                            spu_specs_dict[op_2] = {sku_id}

        spu_options = {}
        for op, val in spu_specs_dict.items():
            if op[0] not in spu_options:
                spu_options[op[0]] = [(op[1], val.pop())]
            else:
                spu_options[op[0]].append((op[1], val.pop()))

        # 渲染页面
        context = {
            'categories': categories,
            'breadcrumb': breadcrumb,
            'sku': sku,
            'specs': spu_options,
        }

        return render(request, 'detail.html', context)
